package cn.sunxiansheng.mybatis.plus.page;

import java.util.Collections;
import java.util.List;
import java.util.function.BiFunction;
import java.util.function.Supplier;

/**
 * Description: 分页逻辑封装
 *
 * @Author sun
 * @Create 2024-10-23 22:27:33
 * @Version 1.0
 */
public class SunPageHelper {

    /**
     * 执行分页操作
     *
     * @param pageNo          页码
     * @param pageSize        每页记录数
     * @param totalSupplier   获取总记录条数的逻辑
     * @param recordsSupplier 获取记录列表的逻辑
     * @param <T>             记录的类型
     * @return 分页结果
     */
    public static <T> PageResult<T> paginate(Long pageNo, Long pageSize,
                                             Supplier<Long> totalSupplier,
                                             BiFunction<Long, Long, List<T>> recordsSupplier) {
        // 计算总记录数
        Long total;
        try {
            total = totalSupplier.get();
        } catch (Exception e) {
            throw new RuntimeException("Failed to get total count", e);
        }

        // 如果总记录数为0，返回空的 PageResult
        if (total == 0) {
            return new PageResult.Builder<T>()
                    .pageNo(pageNo)
                    .pageSize(pageSize)
                    .total(total)
                    .result(Collections.emptyList()) // 空列表
                    .build();
        }

        // 计算 offset，表示从第几条记录开始查询
        Long offset = calculateOffset(pageNo, pageSize);

        // 获取当前页的记录列表
        List<T> records;
        try {
            records = recordsSupplier.apply(offset, pageSize);
        } catch (Exception e) {
            throw new RuntimeException("Failed to get records", e);
        }

        // 使用 Builder 模式创建 PageResult 对象并返回
        return new PageResult.Builder<T>()
                .pageNo(pageNo)
                .pageSize(pageSize)
                .total(total)
                .result(records)
                .build();
    }

    /**
     * 计算分页的 offset
     *
     * @param pageNo   页码
     * @param pageSize 每页记录数
     * @return offset
     */
    public static Long calculateOffset(Long pageNo, Long pageSize) {
        // offset 计算公式：(当前页码 - 1) * 每页记录数
        return (pageNo - 1) * pageSize;
    }
}
